package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Vector3D;
	
	/**
	 * ...
	 * @author Guillaume Sylvain
	 */
	public class Main extends Sprite 
	{
		private const MAX_BOID:int = 1000;
		
		private var mBoidList:Vector.<Boid> = new Vector.<Boid>();
		private var mScreenCenterX:Number 	= 0;
		private var mScreenCenterY:Number 	= 0;
		
		public function Main():void 
		{
			if (stage) Init();
			else addEventListener(Event.ADDED_TO_STAGE, Init);
		}
		
		private function Init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, Init);
			
			stage.quality = "low";
			mScreenCenterX = this.stage.stageWidth / 2;
			mScreenCenterY = this.stage.stageHeight / 2;
			
			// Create boids
			for (var i:int = 0; i < MAX_BOID; i++)
			{
				mBoidList.push(new Boid());
			}
			
			// Assign friends and enemies
			for (i = 0; i < MAX_BOID; i++)
			{
				Assign(mBoidList[i], i);
				mBoidList[i].SetBindPos(mScreenCenterX, mScreenCenterY);
				RandomPos(mBoidList[i]);
				addChild(mBoidList[i]);
			}
			
			// Start updating
			addEventListener(Event.ENTER_FRAME, OnEnterFrame);
		}
		
		private function Assign(aBoid:Boid, aIndex:int):void
		{
			// Attemp to assign a friend to this boid (do not set itself)
			var randomFriend1:int = 0;
			do
			{
				randomFriend1 = RandomInt(0, MAX_BOID - 1);
			}
			while (aIndex == randomFriend1)
			
			// Attemp to assign an enemy (do not set itself or its friend)
			var randomFriend2:int = 0;
			do
			{
				randomFriend2 = RandomInt(0, MAX_BOID - 1);
			}
			while (aIndex == randomFriend2 || randomFriend1 == randomFriend2)
			
			aBoid.mFriend = mBoidList[randomFriend1];
			aBoid.mEnemy = mBoidList[randomFriend2];
		}
		
		private var mFrameCpt:int = 10;
		private function OnEnterFrame(aEvent:Event):void
		{
			for (var i:int = 0; i < MAX_BOID; i++)
			{
				mBoidList[i].Update();
			}
			
			mFrameCpt--;
			
			// Add some chaos - each 10 frames, find a random boid and
			// reinject it with new friend/enemy/position
			if (mFrameCpt <= 0)
			{
				mFrameCpt = 10;
				
				var rnd:int = RandomInt(0, MAX_BOID - 1);
				Assign(mBoidList[rnd], rnd);
				RandomPos(mBoidList[rnd]);
			}
		}
		
		private function RandomInt(aMin:int, aMax:int):int
		{
			return (Math.floor(Math.random() * (aMax - aMin + 1)) + aMin); 
		}
		
		private function RandomNumber(aMin:Number, aMax:Number):Number
		{
			return aMin + (Math.random() * (aMax - aMin));
		}
		
		private function RandomPos(aBoid:Boid):void
		{
			aBoid.x = RandomNumber(0, stage.stageWidth);
			aBoid.y = RandomNumber(0, stage.stageHeight);
		}
	}
}